/*
 * Copyright 2001-2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package code.buildit.plugin.processor;

import code.buildit.plugin.processor.filter.FieldFilter;
import code.buildit.plugin.util.Logger;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;

import java.util.List;

public class BuildItProcessor {
    final private Logger logger = Logger.getInstance(getClass());

    public void process(PsiClass clazz, PsiField[] newFields, boolean reformat) {

        List<PsiField> filteredList = new FieldFilter().filter(clazz, newFields);
        addFilteredMethods(clazz, filteredList);
        if (reformat) formatClass(clazz);
    }

    private void formatClass(PsiClass clazz) {
        try {
            clazz.getManager().getCodeStyleManager().reformat(clazz);
        } catch (IncorrectOperationException e) {
            logger.debug(e.getMessage());
        }
    }

    private void addFilteredMethods(PsiClass clazz, List<PsiField> filteredList) {
        for (PsiField field : filteredList) {
            addField(clazz, field);
        }
        for (PsiField field : filteredList) {
            addMethod(clazz, field);
        }
    }

    private void addField(PsiClass clazz, PsiField field) {
        PsiField existingPsiField = clazz.findFieldByName(field.getName(), false);
        if (existingPsiField != null)
            return;

        try {
            PsiField psiField = PsiTreeUtil.getChildOfType(clazz, PsiField.class);
            clazz.addAfter(field, psiField);
        } catch (IncorrectOperationException e) {
            logger.debug(e.getMessage());
        }
    }

    private void addMethod(PsiClass clazz, PsiField field) {
        try {
            PsiMethod newMethod = new ElementBuilder().constructMethod(clazz, field);
            clazz.addBefore(newMethod, clazz.getRBrace());
        } catch (IncorrectOperationException e) {
            logger.debug(e.getMessage());
        }
    }

}
